namespace Warehouse

open System
open System.Windows.Data
open System.Windows.Controls
open System.Windows.Input
open System.Linq
open FSharp.Windows
open Warehouse.Controls

type PurchaseOrderEvents = 
    | Search
    | Edit
    | Save
    | PreviewLineItemDelete of CancelableEvent
    | DeleteLineItem
    | AddLineItem
    | SelectedPurchaseOrderChanged of PurchaseOrderDetailsModel * PurchaseOrderDetailsModel
    | LineItemModified of ColumnName
    | Print
    | EMail

type PurchaseOrderView(control) as this = 
    inherit PartialView<PurchaseOrderEvents, PurchaseOrderModel, PurchaseOrderControl>(control)

    let items = this.Control.Items
    let lineItems = this.Control.LineItems

    do
        this.Control.Last.EnsurePositiveInt()

    override this.EventStreams = 
        let buttonClicks = 
            [
                this.Control.Search, Search

                this.Control.Save, Save
                this.Control.Print, Print
                this.Control.EMail, EMail

                this.Control.AddLineItem, AddLineItem
                this.Control.DeleteLineItem, DeleteLineItem
            ] 
            |> List.ofButtonClicks

        [
            yield! buttonClicks

            yield lineItems.PreviewKeyDown |> Event.filter(fun event -> event.Key = Key.Delete) |> Event.mapToCancelable PreviewLineItemDelete
            yield lineItems.KeyDown |> Observable.choose(fun event -> if event.Key = Key.Insert then Some AddLineItem else None)

            yield items.SelectionChanged |> Observable.map(fun event -> 
                SelectedPurchaseOrderChanged(
                    event.RemovedItems.Cast().SingleOrDefault(), 
                    event.AddedItems.Cast().SingleOrDefault()
                ))

            yield items.DoubleClickRowEvent() |> Observable.mapTo Edit

            yield lineItems.CellEditEnding |> Observable.choose(fun eventArgs -> 
                if eventArgs.EditAction = DataGridEditAction.Commit 
                then 
                    eventArgs.Column.Header |> string |> LineItemModified |> Some 
                else 
                    None
            )
        ]

    override this.SetBindings model = 
        Binding.FromExpression 
            <@
                this.Control.Save.IsEnabled <- isNotNull model.SelectedPurchaseOrder
                this.Control.Print.IsEnabled <- isNotNull model.SelectedPurchaseOrder
                this.Control.EMail.IsEnabled <- isNotNull model.SelectedPurchaseOrder
                this.Control.AddLineItem.IsEnabled <- isNotNull model.SelectedPurchaseOrder
                this.Control.DeleteLineItem.IsEnabled <- isNotNull model.SelectedLineItem
            @>            

        Binding.FromExpression(
            <@ this.Control.Filter.Text <- model.Filter @>, 
            BindingMode.OneWayToSource, 
            UpdateSourceTrigger.PropertyChanged)

        Binding.FromExpression(
            <@
                this.Control.Last.Text <- string model.Last
            @>,
            targetNullValue = ""
        )

        items.SetBindings(
            model,
            itemsSource = <@ model.Items @>,
            selectedItem = <@ model.SelectedPurchaseOrder @>,
            columnBindings = fun item ->
                [
                    this.Control.ItemsOrderId, <@@ String.Format("PO#{0}", item.Id) @@>
                    this.Control.ItemsCompany, <@@ item.Vendor.CompanyName @@>
                    this.Control.ItemsDate, <@@ String.Format("{0:d}", item.Date) @@>
                    this.Control.ItemsProducts, <@@ item.LineItems.Count @@>
                    this.Control.ItemsQuantity, <@@ item.TotalQuantity @@>
                    this.Control.ItemsTotal, <@@ String.Format("{0:c}", item.Total) @@>
                ]
        )

        lineItems.SetBindings(
            model, 
            itemsSource = <@ model.SelectedPurchaseOrder.LineItems @>,
            selectedItem = <@ model.SelectedLineItem @>,
            columnBindings = fun item ->
                [
                    this.Control.LineItemsUPC, <@@ item.UPCode @@>
                    this.Control.LineItemsBrand, <@@ item.UPC.Product.ProductName.Brand.Name @@>
                    this.Control.LineItemsProduct, <@@ item.UPC.Product.ProductName.Name @@>
                    this.Control.LineItemsSize, <@@ item.Size @@>
                    this.Control.LineItemsQty, <@@ item.Quantity @@>
                    this.Control.LineItemsBase, <@@ String.Format("{0:c}", item.BasePrice) @@>
                    this.Control.LineItemsPct, <@@ item.Commission @@>
                    this.Control.LineItemsExtendedPrice, <@@ String.Format("{0:c}", item.ExtendedPrice) @@>
                    this.Control.LineItemsTotal, <@@ String.Format("{0:c}", item.Total) @@>
                ]
        )
